home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-2.iso / Files II / Prog / N-P / OOP for C.sit / OIC.ƒ / oic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-12-09  |  16.2 KB  |  717 lines  |  [TEXT/KAHL]

  1. /*
  2.  *        Objects-in-C object manager
  3.  *
  4.  *            Copyright © John Wainwright 1988
  5.  *
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include "oic.h"
  10. #include "generics.h"
  11. #include "varargs.h"
  12.  
  13. #define CHECK_OBJS    1                /* turn on or off object checking         */
  14.  
  15. class              currentClass;        /* class of currently exec'ing method    */
  16. MethodTable        *currentGeneric;    /* current generic function table        */
  17.  
  18. static int        trace;                 /* trace flag                             */
  19. static class      trace_class;        /* class for class constrained trace     */
  20. static object    trace_obj;             /* obj for obj constrained trace         */
  21. static int        mth_level;            /* mth nest level                         */
  22. static int        class_index;        /* class index generator                */
  23.  
  24. /*---------------------------- Class Maker  -----------------------------    */
  25.  
  26. /*    
  27.  *     create a new class.
  28.  */
  29. class  
  30. NewClass(ivsize, cvsize, name, va_alist)
  31.     int        ivsize, cvsize;
  32.     char    *name;
  33.     va_dcl
  34. {
  35.     va_list             pvar;
  36.     register class       c;
  37.     register class       superclass;
  38.     register classlist  **cl;
  39.     register int        cvallocz;
  40.     register int        nsupers;
  41.     char                *strcpy(), *salloc();
  42.  
  43.     c = talloc(struct class);
  44.     c->c_classtag = Class;
  45.     c->c_index = ++class_index;
  46.     c->c_name = strcpy(salloc(strlen(name) + 1), name);
  47.     ivsize = (ivsize + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
  48.     cvsize = (cvsize + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
  49.     c->c_next = classes;
  50.     classes = c;
  51.     
  52.     /* build the supers list */
  53.     
  54.     c->c_ivsize = c->c_cvsize = 0;
  55.     cl = &c->c_superclasses;
  56.     va_start(pvar);
  57.     for (nsupers = 0;  (superclass = va_arg(pvar, class)) != END; )
  58.     {
  59.         if (superclass->c_classtag != Class)
  60.             fprintf(stderr, "NewClass (%s): super %d is not a class\n", name, nsupers+1);            
  61.         *cl = talloc(classlist);
  62.         (*cl)->cl_class = superclass;
  63.         cl = &(*cl)->cl_next;
  64.         c->c_ivsize += superclass->c_ivsize;
  65.         c->c_cvsize += superclass->c_cvsize;
  66.         nsupers += 1;
  67.     }
  68.     
  69.     if (nsupers == 0)        /* inherit, at least, from Object        */
  70.     {
  71.         *cl = talloc(classlist);
  72.         (*cl)->cl_class = Object;
  73.         cl = &(*cl)->cl_next;
  74.     }
  75.     
  76.     *cl = END;
  77.     
  78.     /* compute complete object's allocation size */
  79.     
  80.     c->c_ivoffset = c->c_ivsize + sizeof(object);
  81.     c->c_ivsize += ivsize;
  82.     c->c_allocz = c->c_ivsize + sizeof(object);
  83.     
  84.     /*
  85.      *  alocate any class variable structure for this class
  86.      */
  87.     c->c_cvoffset = c->c_cvsize;
  88.     c->c_cvsize += cvsize;
  89.     if (c->c_cvsize)
  90.         c->c_classvars = scalloc(c->c_cvsize);
  91.     else 
  92.         c->c_classvars = 0;
  93.         
  94.     return c;
  95. }
  96.  
  97. int
  98. IsA(obj, c)
  99.     register object        obj;
  100.     register class      c;
  101. {
  102.     return (c == *obj);
  103. }
  104.  
  105. int
  106. IsAKindOf(obj, c)
  107.     register object        obj;
  108.     register class      c;
  109. {
  110.     register classlist      *cl;
  111.  
  112.     if (c == *obj)
  113.         return 1;
  114.     else
  115.         for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  116.             if (IsAKindOf(obj, cl->cl_class))
  117.                 return 1;
  118.     return 0;
  119. }
  120.  
  121. char *
  122. ClassNameOf(obj)
  123.     object    obj;
  124. {
  125.     return    (*obj)->c_name;
  126. }
  127.  
  128. int
  129. IsObj(obj)            /* attempts to tell if this is a valid object */
  130.     object    obj;
  131. {
  132.     return (obj != 0 &&
  133.             ((long)obj & ~0x1L) == (long)obj &&
  134.             ((long)obj & 0xFFFFFF) <= (long)ApplLimit && 
  135.             ClassOf(obj) != 0 && 
  136.             ((long)ClassOf(obj) & ~0x1L) == (long)ClassOf(obj) &&
  137.             ((long)ClassOf(obj) & 0xFFFFFF) <= (long)ApplLimit &&
  138.             ClassOf(obj)->c_classtag == Class);
  139. }
  140.  
  141. InitOIC()
  142. {
  143.     /*
  144.      * Bootstrap the Class system... 
  145.      * Make initial classes and hand patch those bits that assume
  146.      * they already exist.
  147.      */
  148.     Class = NewClass(sizeof(struct class), 0, "Class", END);
  149.     Class->c_classtag = Class;
  150.     Object = NewClass(0, 0, "Object", END);
  151.     free(Object->c_superclasses);
  152.     Object->c_superclasses = END;
  153.     Class->c_superclasses->cl_class = Object;
  154.     _InitObject();
  155.     _InitClass();
  156. }
  157.  
  158. /* ------------------------ Method Tables Manager --------------------- */
  159.  
  160. /*
  161.  *         add methods for a given class to generic function method tables.
  162.  *        The class is given followed by a NULL-terminated list of pairs
  163.  *        of methodTable & local function addresses.
  164.  */
  165. AddMethods(c, va_alist)
  166.     class          c;
  167.     va_dcl
  168. {
  169.     va_list                 pvar;
  170.     register MethodTable    *mth;
  171.     
  172.     for (va_start(pvar); (mth = va_arg(pvar, MethodTable *)) != END; )
  173.     {
  174.         if (mth->mth_funcs == 0)
  175.         {    
  176.             mth->mth_minClass = c->c_index;
  177.             mth->mth_maxClass = c->c_index;
  178.             mth->mth_funcs = (MethodFunc *)scalloc(sizeof(MethodFunc));
  179.         }        
  180.         else if (c->c_index < mth->mth_minClass)
  181.         {
  182.             realloc_funcTable(mth, c->c_index - mth->mth_minClass);
  183.             mth->mth_minClass = c->c_index;
  184.         }
  185.         else if (c->c_index > mth->mth_maxClass)
  186.         {
  187.             realloc_funcTable(mth, c->c_index - mth->mth_maxClass);
  188.             mth->mth_maxClass = c->c_index;
  189.         }
  190.         
  191.         mth->mth_funcs[c->c_index - mth->mth_minClass].mf_func =
  192.             (object (*)())va_arg(pvar, char *);
  193.         mth->mth_funcs[c->c_index - mth->mth_minClass].mf_from = c;
  194.     }
  195. }
  196.  
  197. /*
  198.  *         add class methods for a given class to generic function method tables.
  199.  */
  200. AddClassMethods(c, va_alist)
  201.     class          c;
  202.     va_dcl
  203. {
  204.     va_list                 pvar;
  205.     register MethodTable    *mth;
  206.     
  207.     for (va_start(pvar); (mth = va_arg(pvar, MethodTable *)) != END; )
  208.     {
  209.         mth += 1;        /* point to class table */
  210.         if (mth->mth_funcs == 0)
  211.         {    
  212.             mth->mth_minClass = c->c_index;
  213.             mth->mth_maxClass = c->c_index;
  214.             mth->mth_funcs = (MethodFunc *)scalloc(sizeof(MethodFunc));
  215.         }        
  216.         else if (c->c_index < mth->mth_minClass)
  217.         {
  218.             realloc_funcTable(mth, c->c_index - mth->mth_minClass);
  219.             mth->mth_minClass = c->c_index;
  220.         }
  221.         else if (c->c_index > mth->mth_maxClass)
  222.         {
  223.             realloc_funcTable(mth, c->c_index - mth->mth_maxClass);
  224.             mth->mth_maxClass = c->c_index;
  225.         }
  226.         
  227.         mth->mth_funcs[c->c_index - mth->mth_minClass].mf_func =
  228.             (object (*)())va_arg(pvar, char *);
  229.         mth->mth_funcs[c->c_index - mth->mth_minClass].mf_from = c;
  230.     }
  231. }
  232.  
  233. /*
  234.  *        extend a generic function's method function table.
  235.  *        -ve adjustment => add to front, +ve add to end.
  236.  */
  237. static
  238. realloc_funcTable(mth, adjustment)
  239.     register MethodTable    *mth;
  240.     register int            adjustment;
  241. {
  242.     register int             i, n;
  243.     register MethodFunc        *funcs;    
  244.     
  245.     n = mth->mth_maxClass - mth->mth_minClass + 1;
  246.     funcs = (MethodFunc *)scalloc(sizeof(MethodFunc) * (n + abs(adjustment)));
  247.  
  248.     for (i = 0; i < n; i++)
  249.         funcs[i - ((adjustment < 0) ? adjustment : 0)] = mth->mth_funcs[i];
  250.     
  251.     if (mth->mth_funcs)
  252.         free(mth->mth_funcs);
  253.     mth->mth_funcs = funcs;
  254. }
  255.  
  256. char *
  257. MethodName(mth)
  258.     register MethodTable    *mth;
  259. {
  260.     return mth->mth_name;
  261. }
  262.  
  263. /*------------------------ Method Dispatcher -------------------------*/
  264.  
  265. /*  find the method's function
  266.  *
  267.  *    does a breadth-first search of the superclass DAG looking for a
  268.  *    method function. Caches the function in the local class if inherited.
  269.  */
  270. static object
  271. ((*getMethodFunc(c, mth))())
  272.     register class       c;
  273.     register MethodTable *mth;
  274. {
  275.     register classlist      *cl;
  276.     register int            i;
  277.     register object            (*func)();
  278.     register MethodFunc        *mf, *smf;
  279.  
  280.     /* 
  281.      * check this class
  282.      */
  283.     i = c->c_index - mth->mth_minClass;
  284.     mf = &mth->mth_funcs[i];
  285.     if (i >= 0 && c->c_index <= mth->mth_maxClass &&
  286.         (func = mf->mf_func) != NULL)
  287.     {
  288.         currentClass =  mf->mf_from;
  289.         return func;
  290.     }
  291.     
  292.     /*
  293.      *  else, check immediate supers in breadth-first search
  294.      */
  295.     for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  296.     {
  297.         i = cl->cl_class->c_index - mth->mth_minClass;
  298.         smf = &mth->mth_funcs[i];
  299.         if (i >= 0 && cl->cl_class->c_index <= mth->mth_maxClass &&
  300.             (func = smf->mf_func) != NULL)
  301.         {
  302.             /*
  303.              * inherited, cache it in the local class's method table
  304.              */
  305.             AddMethods(c, mth, func, NULL);
  306.             currentClass = 
  307.                 mth->mth_funcs[cl->cl_class->c_index - mth->mth_minClass].mf_from;
  308.             mth->mth_funcs[c->c_index - mth->mth_minClass].mf_from =
  309.                 currentClass;
  310.             return func;
  311.         }
  312.     }
  313.     
  314.     /*
  315.      *     else, recurse down the superclass DAG
  316.      */
  317.     for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  318.         if ((func = getMethodFunc(cl->cl_class, mth)) != NULL)
  319.         {
  320.             AddMethods(c, mth, func, NULL);
  321.             mth->mth_funcs[c->c_index - mth->mth_minClass].mf_from =
  322.                 currentClass;
  323.             return func;
  324.         }
  325.         
  326.     return NULL;
  327. }
  328.  
  329. /*
  330.  *    dispatch a generic's method function. 
  331.  *
  332.  *  also keeps track of the class in which this current method was found.
  333.  */
  334. object
  335. Method(mth, obj, args)
  336.     register MethodTable    *mth;
  337.     register object            obj;
  338.     char                    *args;
  339. {
  340.     register object    (*func)();
  341.     class              saveCurrentClass;
  342.     MethodTable        *saveCurrentGeneric;
  343.     
  344. #ifdef CHECK_OBJS
  345.     if (!IsObj(obj))
  346.     {
  347.         fprintf(stderr, "** method (%s) to non-object (%lx)\n", mth->mth_name, obj);
  348.         return NULL;
  349.     }
  350. #endif
  351.  
  352.     saveCurrentClass = currentClass;
  353.     saveCurrentGeneric = currentGeneric;
  354.     if ((func = getMethodFunc(*obj, mth)) != NULL)
  355.     {
  356.         if (trace)
  357.             traceMethod(mth, obj);
  358.         mth_level += 1;
  359.         currentGeneric = mth;
  360.         obj = (*func)(obj, &((char *)obj)[currentClass->c_ivoffset], args);
  361.  
  362.         mth_level -= 1;
  363.         currentClass = saveCurrentClass;
  364.         currentGeneric = saveCurrentGeneric;
  365.         
  366.         return obj;
  367.     }
  368.  
  369.     fprintf(stderr, "** No \"%s\" method for %s\n", mth->mth_name, ClassNameOf(obj));
  370. }
  371.  
  372. /*
  373.  *    dispatch a generic's class method function.
  374.  *    
  375.  *    given the class method function table. calls the function with class
  376.  *    and local class variable structure as the 1st 2 args.
  377.  *
  378.  *    if a class method is not found, attempts to invoke the generic as a
  379.  *  normal method on class 'class'.
  380.  *
  381.  *    this function, which could have been integrated with 'Method', is a
  382.  *    separate function in the interests of efficiency.
  383.  */
  384. object
  385. ClassMethod(mth, c, args)
  386.     register MethodTable    *mth;
  387.     register class          c;
  388.     char                    *args;
  389. {
  390.     register object    (*func)();
  391.     register object    obj;
  392.     class              saveCurrentClass;
  393.     MethodTable        *saveCurrentGeneric;
  394.  
  395. #ifdef CHECK_OBJS
  396.     if (c->c_classtag != Class)
  397.     {
  398.         fprintf(stderr, "** class method (%s) to non-class (%lx)\n", mth->mth_name, c);
  399.         return  NULL;
  400.     }
  401. #endif
  402.  
  403.     saveCurrentClass = currentClass;
  404.     saveCurrentGeneric = currentGeneric;
  405.     if ((func = getMethodFunc(c, mth)) != NULL)
  406.     {
  407.         if (trace)
  408.             traceClassMethod(mth, c);
  409.         mth_level += 1;
  410.  
  411.         currentGeneric = mth;
  412.         obj = (*func)(c, &(c->c_classvars)[currentClass->c_cvoffset], args);
  413.  
  414.         mth_level -= 1;
  415.         currentClass = saveCurrentClass;
  416.         currentGeneric = saveCurrentGeneric;
  417.         
  418.         return obj;
  419.     }
  420.     else
  421.         return Method(&mth[-1], c, args);    
  422.  
  423.     fprintf(stderr, "** No \"%s\" class method for %s\n", mth->mth_name, c->c_name);
  424. }
  425.  
  426. /*  
  427.  *    called by Super to find the method definition next up the superclass
  428.  *    DAG from the current method's class.
  429.  *
  430.  *    does a breadth-first search of the superclass DAG looking for the
  431.  *    method function inherited from the supers further than 'currentClass'.
  432.  *
  433.  *    this function, a slight variant of 'getMethodFunc', is a
  434.  *    separate function in the interests of efficiency.
  435.  */
  436. static object
  437. ((*getSuperMethodFunc(c, mth, beyond))())
  438.     register class       c;
  439.     register MethodTable *mth;
  440.     int         beyond;
  441. {
  442.     register classlist      *cl;
  443.     register int            i;
  444.     register object            (*func)();
  445.     register MethodFunc        *mf, *smf;
  446.  
  447.     /* 
  448.      * check this class
  449.      */
  450.     i = c->c_index - mth->mth_minClass;
  451.     mf = &mth->mth_funcs[i];
  452.     
  453.     if (mf->mf_from == currentClass)
  454.         beyond = 1;
  455.  
  456.     if (beyond &&
  457.         mf->mf_from != currentClass &&     /* ignore current method's class    */
  458.         i >= 0 && c->c_index <= mth->mth_maxClass &&
  459.         (func = mf->mf_func) != NULL)
  460.     {
  461.         currentClass =  mf->mf_from;
  462.         return func;
  463.     }
  464.     
  465.     /*
  466.      *  else, check immediate supers in breadth-first search
  467.      */
  468.     for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  469.     {
  470.         i = cl->cl_class->c_index - mth->mth_minClass;
  471.         smf = &mth->mth_funcs[i];
  472.         
  473.         if (smf->mf_from == currentClass)
  474.             beyond = 1;
  475.  
  476.         if (beyond &&
  477.             smf->mf_from != currentClass &&
  478.             i >= 0 && cl->cl_class->c_index <= mth->mth_maxClass &&
  479.             (func = smf->mf_func) != NULL)
  480.         {
  481.             currentClass = smf->mf_from;
  482.             return func;
  483.         }
  484.     }
  485.     
  486.     /*
  487.      *     else, recurse down the superclass DAG
  488.      */
  489.     for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  490.         if ((func = getSuperMethodFunc(cl->cl_class, mth, beyond)) != NULL)
  491.             return func;
  492.         
  493.     return NULL;
  494. }
  495.  
  496. object
  497. Super(obj, args)
  498.     object                    obj;
  499.     char                    *args;
  500. {
  501.     register object    (*func)();
  502.     class              saveCurrentClass;
  503.  
  504. #ifdef CHECK_OBJS
  505.     if (!IsObj(obj))
  506.     {
  507.         fprintf(stderr, "** super method (%s) on non-object (%lx)\n", currentGeneric->mth_name, obj);
  508.         return NULL;
  509.     }
  510. #endif
  511.  
  512.     saveCurrentClass = currentClass;
  513.     if ((func = getSuperMethodFunc(*obj, currentGeneric, 0)) != NULL)
  514.     {
  515.         if (trace)
  516.             traceSuperMethod(currentGeneric, obj);
  517.         mth_level += 1;
  518.  
  519.         obj = (*func)(obj, &((char *)obj)[currentClass->c_ivoffset], &args);
  520.  
  521.         mth_level -= 1;
  522.         currentClass = saveCurrentClass;
  523.         
  524.         return obj;
  525.     }
  526.  
  527.     fprintf(stderr, "** No \"%s\" super method for %s\n", currentGeneric->mth_name, ClassNameOf(obj));
  528. }
  529.  
  530. /*
  531.  *    Identical to 'Super', above, except that a pointer to the argument
  532.  *    list is given instead of them being in place.
  533.  *
  534.  *    This allows methods to easily pass their arguments up to the super 
  535.  *    they are invoking (e.g., see 'new' in IndexMixin).
  536.  *
  537.  *    Like other variant functions, it is a separate function in the
  538.  *    interests of efficiency.
  539.  */
  540. object
  541. SuperPassArgs(obj, argp)
  542.     object                    obj;
  543.     char                    **argp;
  544. {
  545.     register object    (*func)();
  546.     class              saveCurrentClass;
  547.  
  548. #ifdef CHECK_OBJS
  549.     if (!IsObj(obj))
  550.     {
  551.         fprintf(stderr, "** super method (%s) on non-object (%lx)\n", currentGeneric->mth_name, obj);
  552.         return NULL;
  553.     }
  554. #endif
  555.  
  556.     saveCurrentClass = currentClass;
  557.     if ((func = getSuperMethodFunc(*obj, currentGeneric, 0)) != NULL)
  558.     {
  559.         if (trace)
  560.             traceSuperMethod(currentGeneric, obj);
  561.         mth_level += 1;
  562.  
  563.         obj = (*func)(obj, &((char *)obj)[currentClass->c_ivoffset], argp);
  564.  
  565.         mth_level -= 1;
  566.         currentClass = saveCurrentClass;
  567.         
  568.         return obj;
  569.     }
  570.  
  571.     fprintf(stderr, "** No \"%s\" super method for %s\n", currentGeneric->mth_name, ClassNameOf(obj));
  572. }
  573.  
  574. /*---------------------------- Object Maker -----------------------------*/
  575.  
  576. /* 
  577.  *    creates a new instance of the given class. Inits all instance vars to
  578.  *    zero, and sends 'new' to it.
  579.  */ 
  580. object
  581. New(c, args)
  582.     register class       c;
  583.     char                *args;
  584. {
  585.     register object    obj;
  586.     register char    *p;
  587.  
  588.     obj = (object)scalloc(c->c_allocz);
  589.     *obj = c;
  590.     Method(newGeneric, obj, &args);    /* send it the 'new' message    */
  591.     
  592.     return obj;
  593. }
  594.  
  595. int
  596. SizeOf(obj)
  597.     object    obj;
  598. {
  599.     return    ClassOf(obj)->c_allocz;
  600. }
  601.  
  602.  
  603. static
  604. traceMethod(mth, obj)
  605.     MethodTable    *mth;
  606.     object        obj;
  607. {
  608.     if (trace_class == NULL || *obj == trace_class &&
  609.         trace_obj == NULL || obj == trace_obj)
  610.     {
  611.         fprintf(stderr, "%.*s%s ", mth_level, 
  612.             mth_level ? ".............." : "", MethodName(mth));
  613.         if (ClassOf(obj) != currentClass)
  614.             fprintf(stderr, "(from %s) ", currentClass->c_name);
  615.         fprintf(stderr, "on %s @%lx\n", ClassNameOf(obj), obj);
  616.     }
  617. }
  618.  
  619. static
  620. traceClassMethod(mth, c)
  621.     MethodTable    *mth;
  622.     object        c;
  623. {
  624.     if (trace_class == NULL || ClassOf(c) == trace_class &&
  625.         trace_obj == NULL || c == trace_obj)
  626.     {
  627.         fprintf(stderr, "%.*s%s ", mth_level, 
  628.             mth_level ? ".............." : "", MethodName(mth));
  629.         if ((class)c != currentClass)
  630.             fprintf(stderr, "(from %s) ", currentClass->c_name);
  631.         fprintf(stderr, "on class %s @%lx\n", ((class)c)->c_name, c);
  632.     }
  633. }
  634.  
  635. static
  636. traceSuperMethod(mth, obj)
  637.     MethodTable    *mth;
  638.     object        obj;
  639. {
  640.     if (trace_class == NULL || *obj == trace_class &&
  641.         trace_obj == NULL || obj == trace_obj)
  642.     {
  643.         fprintf(stderr, "%.*ssuper %s ", mth_level, 
  644.             mth_level ? ".........." : "", MethodName(mth));
  645.         if (ClassOf(obj) != currentClass)
  646.             fprintf(stderr, "(from %s) ", currentClass->c_name);
  647.         fprintf(stderr, "on %s @%lx\n", ClassNameOf(obj), obj);
  648.     }
  649. }
  650.  
  651. TraceOn()
  652. {
  653.     trace = 1;
  654. }
  655.  
  656. TraceOff()
  657. {
  658.     trace = 0;
  659.     trace_obj = NULL;
  660.     trace_class = NULL;
  661. }
  662.  
  663. TraceObj(obj)
  664.     object    obj;
  665. {
  666.     trace = 1;
  667.     trace_obj = obj;
  668. }
  669.  
  670. TraceClass(c)
  671.     class      c;
  672. {
  673.     trace = 1;
  674.     trace_class = c;
  675. }
  676.  
  677. dumpClass(c)
  678.     register class      c;
  679. {
  680.     register classlist      *cl;
  681.  
  682.     fprintf(stderr, "Class \"%s\" :\n", c->c_name);
  683.     fprintf(stderr, "  supers : (");
  684.     for (cl = c->c_superclasses; cl != END; cl = cl->cl_next)
  685.         fprintf(stderr, "%s%s", cl->cl_class->c_name, (cl->cl_next) ? "," : "");
  686.     fprintf(stderr, ")\n  index %d\n  cv\'s %lx, offset %d\n", c->c_index,
  687.         c->c_classvars, c->c_cvoffset);
  688. }
  689.  
  690. dumpMethodTable(mth)
  691.     register MethodTable    *mth;
  692. {
  693.     register int i, l;
  694.     
  695.     fprintf(stderr, "\"%s\" method table : \n", mth->mth_name);
  696.     fprintf(stderr, "  class indexes : low %d, high %d\n", (l = mth->mth_minClass), mth->mth_maxClass);
  697.     for (i = l; i <= mth->mth_maxClass; i++)
  698.         if (mth->mth_funcs[i - l].mf_func)
  699.             fprintf(stderr, "  (%d) fn %lx from %s\n",
  700.                 i, mth->mth_funcs[i - l].mf_func,
  701.                 (mth->mth_funcs[i - l].mf_from)->c_name);
  702. }
  703.  
  704. object
  705. key_arg(arglist, key, default_arg)
  706.     register keyword_args    arglist;
  707.     int                        key;
  708.     object                    default_arg;
  709. {
  710.     for (; *(int *)arglist != key && *(int *)arglist != 0; arglist += sizeof(int) + sizeof(long))
  711.         ;
  712.     if (*(int *)arglist == 0)
  713.         return default_arg;
  714.     else
  715.         return *(object *)(arglist + sizeof(int));
  716. }
  717.